package itsm.isperp.framework.utils;

import itsm.isperp.framework.domain.FileUploadInfo;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.util.Assert;

/**
 * 包含文件上传信息的Request解析工具类.
 * <p>
 * 它的两个parse函数将返回{@link FileUploadInfo}对象.后者封装了表单信息.
 * </p>
 * <br/>
 * <p>
 * 使用方式举例:<br/>
 * 1.解析Request,使用默认字符集(<strong>UTF-8</strong>)<br/>
 * <code>FileUploadInfo fileUploadInfo = FileUploadParser.parse(request);</code>
 * <br/>
 * 2.解析Request,使用指定的字符集<br/>
 * <code>FileUploadInfo fileUploadInfo = FileUploadParser.parse(request,"GBK");</code>
 * <br/>
 * </p>
 */
public class FileUploadParser {

	/**
	 * 解析Request,使用默认字符集(UTF-8).
	 * 
	 * @param httpServletRequest
	 *            HttpServletRequest对象.
	 * @return FileUploadInfo对象
	 */
	public FileUploadInfo parse(HttpServletRequest httpServletRequest) {
		return parse(httpServletRequest, DEFAULT_ENCODING);
	}

	/**
	 * 解析Request,使用指定的字符集.
	 * 
	 * @param request
	 *            HttpServletRequest对象.
	 * @param encoding
	 *            字符集.
	 * @return FileUploadInfo对象
	 */
	public FileUploadInfo parse(HttpServletRequest request, String encoding) {
		Assert.notNull(request, "被解析的HttpServletRequest对象不能为空");
		encoding = (null == encoding) ? DEFAULT_ENCODING : encoding;
		if (!ServletFileUpload.isMultipartContent(request)) {
			throw new IllegalArgumentException("上传的表单不是MultiPart类型");
		}
		return parseRequestToUploadFileInfo(request, encoding);
	}

	/**
	 * 解析Request对象,产生FileUploadInfo对象.
	 * <p>
	 * 为保持ServletFileUpload的实例在每次解析Request时使用指定的字符集,
	 * 此函数负责保持ServletFileUpload的字符集在使用过程中不变.
	 * </p>
	 * 
	 * @param request
	 *            HttpServletRequest对象.
	 * @param encoding
	 *            字符集.
	 * @return FileUploadInfo对象
	 */
	protected FileUploadInfo parseRequestToUploadFileInfo(
			HttpServletRequest request, String encoding) {
		String oldHeaderEncoding = null;
		try {
			oldHeaderEncoding = servletFileUpload.getHeaderEncoding();
			servletFileUpload.setHeaderEncoding(encoding);
			List<FileItem> fileItems = parseRequestToFileItems(request);
			FileUploadInfo uploadFileInfo = new FileUploadInfo(fileItems,
					encoding);
			return uploadFileInfo;
		} catch (FileUploadException e) {
			throw new RuntimeException(String.format("文件上传解析错误[%s]",
					e.getMessage()), e);
		} finally {
			servletFileUpload.setHeaderEncoding(oldHeaderEncoding);
		}
	}

	protected List<FileItem> parseRequestToFileItems(HttpServletRequest request)
			throws FileUploadException {
		List<FileItem> fileItems = servletFileUpload.parseRequest(request);
		return fileItems;
	}

	public String DEFAULT_ENCODING = "UTF-8";
	private ServletFileUpload servletFileUpload = new ServletFileUpload(
			new DiskFileItemFactory());
}
